package com.adt.studioms.api;

import java.text.MessageFormat;
import java.util.Calendar;

import com.asao.baseware.core.api.API;
import com.asao.baseware.core.api.IDAOAwareAPI;
import com.asao.baseware.core.api.hibernate.HibernateAPIRegistry;
import com.asao.baseware.core.api.hibernate.PropertyAPI;
import com.asao.baseware.core.dao.hibernate.HibernateDAO;
import com.asao.baseware.core.property.IProperty;
import com.asao.baseware.core.property.Property;
import com.asao.baseware.core.property.PropertyValue;

public class TxCodeGeneratorAPI extends API<HibernateAPIRegistry> implements IDAOAwareAPI<HibernateDAO, HibernateAPIRegistry> {
    private static Object PLOCK = new Object();
    private static Object TLOCK = new Object();
    
    private static final String PAYMENT_TX_PROPERTIES = "PAYMENT_TX_PROPERTIES";
    private static final String TRADE_TX_PROPERTIES = "TRADE_TX_PROPERTIES";
    
    private static final String CODE_PATTERN = "CODE_PATTERN";
    private static final String CODE_YEAR = "CODE_YEAR";
    private static final String CODE_MONTH = "CODE_MONTH";
    private static final String CODE_NO = "CODE_NO";
    
    
    private static final String DEFAULT_PAYMENT_CODE_PATTERN_VALUE = "{0}{1}{2}"; 
    private static final String DEFAULT_TRADE_CODE_PATTERN_VALUE = "PT{0}{1}{2}"; 
    
    HibernateDAO dao;
    
    public HibernateDAO getPersistentEngine() {
        return dao;
    }
    
    public void setPersistentEngine(HibernateDAO dao) {
        this.dao = dao;
    }

    private IProperty createDefaultTxProperties(String txProps, String defaultPatternPropValue) {
        Calendar calendar = Calendar.getInstance();
        int currentYear = calendar.get(Calendar.YEAR);
        int currentMonth = calendar.get(Calendar.MONTH);
        
        Property pcProp = new Property(txProps);
        pcProp.addProperty(CODE_PATTERN, new PropertyValue(defaultPatternPropValue));
        pcProp.addProperty(CODE_YEAR, new PropertyValue(currentYear));
        pcProp.addProperty(CODE_MONTH, new PropertyValue(currentMonth));
        pcProp.addProperty(CODE_NO, new PropertyValue(0));
        dao.save(pcProp);
        
        return pcProp;
    }
    
    private IProperty getTxProperties(String txProps, String defaultPatternPropValue) {
        IProperty pcProp = otherAPI(PropertyAPI.class).getByName(txProps);
        if (pcProp==null)
            pcProp = createDefaultTxProperties(txProps, defaultPatternPropValue);
        
        return pcProp;
    }
    
    private String getNextTxCode(String txProps, String defaultPatternPropValue) {
        Calendar calendar = Calendar.getInstance();
        int currentYear = calendar.get(Calendar.YEAR);
        int currentMonth = calendar.get(Calendar.MONTH);
        
        IProperty pcProp = getTxProperties(txProps, defaultPatternPropValue);
        String pattern = pcProp.getPropertyValue(CODE_PATTERN).getStringValue();
        int year = pcProp.getPropertyValue(CODE_YEAR).getNumberValue().intValue();
        int month = pcProp.getPropertyValue(CODE_MONTH).getNumberValue().intValue();
        int no = pcProp.getPropertyValue(CODE_NO).getNumberValue().intValue();
        
        if (currentYear!=year || currentMonth!=month) {
            year = currentYear;
            pcProp.getProperty(CODE_YEAR).setValue(new PropertyValue(year));
            month = currentMonth;
            pcProp.getProperty(CODE_MONTH).setValue(new PropertyValue(month));
            no = 0;
        }
        ++no;
        pcProp.getProperty(CODE_NO).setValue(new PropertyValue(no));
        
        dao.update(pcProp);
        return MessageFormat.format(pattern, year-2000, month, no);
    }
    
    public String getNextPaymentCode() {
        synchronized (PLOCK) {
            return getNextTxCode(PAYMENT_TX_PROPERTIES, DEFAULT_PAYMENT_CODE_PATTERN_VALUE);
        }
    }
    
    public String getNextTradeCode() {
        synchronized (TLOCK) {
            return getNextTxCode(TRADE_TX_PROPERTIES, DEFAULT_TRADE_CODE_PATTERN_VALUE);
        }
    }
}
